package com.jl.tools.ui.dialog;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.wb.swt.ResourceManager;
import org.eclipse.wb.swt.SWTResourceManager;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.input.sax.XMLReaders;
import com.jl.tools.Activator;
import com.jl.util.HexUtil;
import com.jl.util.SWTDialogUtil;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class SWCommandSearchDialog extends Dialog {

	protected Object result;
	protected Shell shell;
	private Text textSwInput;

	private static HashMap<String, String> swmap = new HashMap<String, String>();
	private static HashMap<Integer, String> cmds = new HashMap<Integer, String>();
	private static HashMap<Integer, TreeItem> topTreeItems = new HashMap<Integer, TreeItem>();
	private static Integer index = 0;
	private Text textOutput;
	private Text textOutputCmd;
	private Text textInputCmd;
	private Text textOutputOne;
	private static Document cmdDoc = null;
	private Tree treeCmd;
	static {// init sw
		URL url = Platform.getBundle(Activator.PLUGIN_ID)
				.getEntry("xml/sw.xml");
		try {
			url = FileLocator.toFileURL(url);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String path = url.getPath();
		SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
		try {
			Document doc = builder.build(new File(path));
			Element root = doc.getRootElement();
			java.util.List<Element> eles = root.getChildren();
			for (Element e : eles) {
				swmap.put(e.getName().substring(2), e.getText().trim());
			}
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	static {// init command
		URL url = Platform.getBundle(Activator.PLUGIN_ID).getEntry(
				"xml/command.xml");
		try {
			url = FileLocator.toFileURL(url);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String path = url.getPath();
		SAXBuilder builder = new SAXBuilder(XMLReaders.NONVALIDATING);
		try {
			cmdDoc = builder.build(new File(path));
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	public SWCommandSearchDialog(Shell parent, int style) {
		super(parent, style);
		setText("SW/Command Search");
		createContents();
		filteListSw("");
		initTree();
	}

	private void initTree() {
		Element root = cmdDoc.getRootElement();
		java.util.List<Element> all = root.getChildren();
		for (int i = 0, end = all.size(); i < end; i++) {
			
			index = i;
			
			TreeItem item_cmd = new TreeItem(treeCmd, SWT.NONE, i);
			String name = all.get(i).getChildText("name");
			item_cmd.setText(name);
			cmds.put(index, name);
			topTreeItems.put(index, item_cmd);
			recuseTree(all.get(i), item_cmd, true);
		}
		// treeCmd.setTopItem(item);
	}

	private void recuseTree(Element ele, TreeItem parent, boolean flag) {
		java.util.List<Element> all = ele.getChildren();
		if (all == null || all.size() <= 0) {
			return;
		}
		for (int i = 0; i < all.size(); i++) {
			String name = all.get(i).getName();
			if (flag) {
				if (name.equalsIgnoreCase("name")) {
					continue;
				}
			}
			
			TreeItem item = new TreeItem(parent, SWT.NONE);
			item.setText(name);
			String data = all.get(i).getText();
			if(name.equalsIgnoreCase("ins")){
				cmds.put(index, cmds.get(index) + data);
			}
			item.setData(data);
			recuseTree(all.get(i), item, false);
		}
	}

	/**
	 * Open the dialog.
	 * 
	 * @return the result
	 */
	public Object open() {
		SWTDialogUtil.locateToParentCenter(getParent(), shell);
		shell.open();
		shell.layout();
		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		return result;
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.MIN | SWT.RESIZE);
		shell.setImage(ResourceManager.getPluginImage("com.jl.smartcard.tools",
				"icons/swcommand_search_16.png"));
		shell.setSize(625, 387);
		shell.setText(getText());
		shell.setLayout(new GridLayout(1, false));

		TabFolder tabFolder = new TabFolder(shell, SWT.NONE);
		tabFolder.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));
		tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1));

		TabItem tbtmSw = new TabItem(tabFolder, SWT.NONE);
		tbtmSw.setText("SW");

		Composite composite = new Composite(tabFolder, SWT.NONE);
		tbtmSw.setControl(composite);
		composite.setLayout(new FormLayout());

		textSwInput = new Text(composite, SWT.BORDER);
		FormData fd_textSwInput = new FormData();
		fd_textSwInput.right = new FormAttachment(0, 100);
		fd_textSwInput.top = new FormAttachment(0, 5);
		fd_textSwInput.left = new FormAttachment(0, 5);
		textSwInput.setLayoutData(fd_textSwInput);
		textSwInput.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				event_modify_text_swinput();
			}
		});
		textSwInput.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		textOutputOne = new Text(composite, SWT.BORDER);
		FormData fd_textOutputOne = new FormData();
		fd_textOutputOne.right = new FormAttachment(100, -10);
		fd_textOutputOne.top = new FormAttachment(0, 5);
		fd_textOutputOne.left = new FormAttachment(0, 105);
		textOutputOne.setLayoutData(fd_textOutputOne);
		textOutputOne.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		textOutput = new Text(composite, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP
				| SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
		FormData fd_textOutput = new FormData();
		fd_textOutput.right = new FormAttachment(textOutputOne, 0, SWT.RIGHT);
		fd_textOutput.bottom = new FormAttachment(100, -10);
		fd_textOutput.top = new FormAttachment(10);
		fd_textOutput.left = new FormAttachment(0, 5);
		textOutput.setLayoutData(fd_textOutput);
		textOutput.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
		textOutput.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		TabItem tbtmCommand = new TabItem(tabFolder, SWT.NONE);
		tbtmCommand.setText("Command");

		Composite composite_1 = new Composite(tabFolder, SWT.NONE);
		tbtmCommand.setControl(composite_1);
		composite_1.setLayout(new GridLayout(1, false));

		SashForm sashForm = new SashForm(composite_1, SWT.NONE);
		sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1));

		Composite composite_2 = new Composite(sashForm, SWT.NONE);
		composite_2.setLayout(new FormLayout());

		treeCmd = new Tree(composite_2, SWT.BORDER);
		treeCmd.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				event_click_tree_cmd(e);
			}
		});
		FormData fd_treeCmd = new FormData();
		fd_treeCmd.top = new FormAttachment(0, 29);
		fd_treeCmd.bottom = new FormAttachment(100);
		fd_treeCmd.left = new FormAttachment(0);
		fd_treeCmd.right = new FormAttachment(100);
		treeCmd.setLayoutData(fd_treeCmd);
		treeCmd.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		textInputCmd = new Text(composite_2, SWT.BORDER);
		textInputCmd.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				event_nodify_text_input_cmd();
			}
		});
		FormData fd_textInputCmd = new FormData();
		fd_textInputCmd.right = new FormAttachment(treeCmd, 0, SWT.RIGHT);
		fd_textInputCmd.top = new FormAttachment(0);
		fd_textInputCmd.left = new FormAttachment(0);
		textInputCmd.setLayoutData(fd_textInputCmd);
		textInputCmd.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		textOutputCmd = new Text(sashForm, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
		textOutputCmd.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));
		textOutputCmd.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_WHITE));
		sashForm.setWeights(new int[] {216, 425});

	}

	protected void event_nodify_text_input_cmd() {
		String input = this.textInputCmd.getText().trim().toUpperCase();
		Set<Entry<Integer, String>>  sets = cmds.entrySet();
		Integer idx = 0;
		for (Entry<Integer, String> entry : sets) {
			String val = entry.getValue();
			if(val.toUpperCase().contains(input)){
				idx = entry.getKey();
				break;
			}
		}
		TreeItem item = topTreeItems.get(idx);
		this.treeCmd.select(item);
		this.treeCmd.showItem(item);
		item.setExpanded(true);
		event_click_tree_cmd(null);
	}

	protected void event_click_tree_cmd(SelectionEvent e) {
		TreeItem[] items = this.treeCmd.getSelection();
		if (items == null)
			return;
		if (items.length > 0) {
			String data = getTreeData(items[0]);
			this.textOutputCmd.setText(data == null ? "" : data);
		}
	}

	private String getTreeData(TreeItem treeItem) {
		StringBuilder sb = new StringBuilder();
		resuseTreeData(treeItem, sb);
		return sb.toString();
	}

	private void resuseTreeData(TreeItem treeItem, StringBuilder sb) {
		if (treeItem == null) {
			return;
		} else {
			String data = (String) treeItem.getData();
			sb.append(treeItem.getText()).append(" :\n")
					.append(data == null ? "" : data.trim()).append('\n');
			TreeItem[] children = treeItem.getItems();
			for (TreeItem item : children) {
				resuseTreeData(item, sb);
			}
		}
	}

	protected void event_modify_text_swinput() {
		String hex = HexUtil.compact(textSwInput.getText());
		String first = filteListSw(hex);
		if (!first.equals("")) {
			first = first.substring(5);
		}
		this.textOutputOne.setText(first);
	}

	private String filteListSw(String sw) {
		Set<String> keys = swmap.keySet();
		Iterator<String> it = keys.iterator();
		StringBuilder sb = new StringBuilder(1024 * 16);
		String all = "";
		if (sw == null || sw.trim().length() == 0) {
			while (it.hasNext()) {
				String str = it.next();
				sb.append(str + " - " + swmap.get(str) + "\n");
			}
		} else {
			while (it.hasNext()) {
				String str = it.next();
				if (str.startsWith(sw)) {
					sb.append(str + " - " + swmap.get(str) + "\n");
				}
			}
		}
		all = sb.toString();
		textOutput.setText(all);
		return all.split("\\n", 2)[0].trim();
	}
}
